import {PluginCommand} from "../PluginCommand";
import {Axis, Direction, Point} from "../../../nodeApp/static/lib/crowncad-plugin-sdk-0.0.1";

class ChainDriveDesignCommand extends PluginCommand {
  constructor() {
    super();
  }

  //方位
  SIDE = {
    UP:1,                 //上
    DOWN:2,               //下
    LEFT:3,               //左
    RIGHT:4,              //右
    FRONT:5,              //前
    AFTER:6,              //后
    IN:7,                 //里
    OUT:8,                //外
    POSITIVE:9,           //正
    NEGATIVE:10,          //反
  }
  //在二维上，一个点绕另一个点旋转一定角度后的结果，旋转角度为逆时针为正，距离为空时默认为两点距离
  rotatePointAroundPoint(pointO,pointA,angle,dis = -1){
    //先将点偏移到原点
    let OA = pointA.clone().sub(pointO);
    let x = this.cos(angle) * OA.x - this.sin(angle) * OA.y;
    let y = this.sin(angle) * OA.x + this.cos(angle) * OA.y;

    let newAPoint = new THREE.Vector3(x,y);
    //如果不是进行的等距离旋转，即OA != OnewA，应该以所延长的距离比上OA所得的点作为延伸点
    if(dis > 0){
      newAPoint.multiplyScalar(dis / (OA.length()));
    }

    newAPoint.add(pointO);

    return newAPoint;
  }
  //在三维上，一个点绕一个轴旋转一定角度后的结果，旋转角度为逆时针为正，距离为空时默认为两点距离
  getLineRevolvePoint(lineDir,linePoint,point,angle,dis = -1){
    //根据轴和角度设计旋转矩阵
    let rotateMatrix = new THREE.Matrix4();
    rotateMatrix.makeRotationAxis(lineDir,angle * Math.PI / 180);

    //将旋转点进行位移到原点为基准的位置
    let directionToPoint = new THREE.Vector3().subVectors(point,linePoint);
    //应用旋转矩阵进行旋转
    directionToPoint.applyMatrix4(rotateMatrix);

    let addVector;
    if(dis > 0){
      addVector = (directionToPoint.normalize()).multiplyScalar(dis);
    }else{
      addVector = directionToPoint;
    }
    //旋转后的点加上基准
    let rotatedPoint = linePoint.clone().add(addVector);
    return rotatedPoint;
  }
  //给定三个点，计算夹角关系，如果给定轴向，则判断正负方向
  getPointsAngle(centerPoint,point1,point2,normal = null){
    let vector1 = point1.clone().sub(centerPoint);
    let vector2 = point2.clone().sub(centerPoint);

    let angle = this.acos((vector1.clone().dot(vector2)) / (vector1.length() * vector2.length()));
    if(normal !== null){
      //两个向量如果同向或者异向，则无正反之分
      if(angle !== 180 && angle !== 0){
        let crossVector = new THREE.Vector3().crossVectors(vector1,vector2);
        //如果叉乘向量与旋转轴法向点乘小于0，则angle为反向
        if(normal.clone().dot(crossVector) < 0){
          angle = -angle;
        }
      }
    }
    return angle;
  }
  //给定两个点作为圆心，给定两个半径，给定一个法向，确定两个圆的交点
  getIntersectPoints(point1,point2,radius1,radius2,normal){
    //圆心距离
    let dis = (point1.clone().sub(point2)).length();
    //求解point2需要绕point1旋转多少角度
    let angle = this.acos((Math.pow(dis,2) + Math.pow(radius1,2) - Math.pow(radius2,2)) / (2 * dis * radius1));
    //绕point1反向旋转angle得到交点
    let pointIntersect = this.rotatePointAroundPoint(point1,point2,angle,radius1);
    return pointIntersect;
  }
  async createArcByCenter(sketch,point1,point2,point3)
  {
    if(!sketch){
      return;
    }
    await sketch.createArcByCenter({
      centerPoint:new Point(point1.x,point1.y),
      startPoint:new Point(point2.x,point2.y),
      endPoint:new Point(point3.x,point3.y)});
  }
  async createSketchLine(sketch,point1,point2){
    if(!sketch){
      return;
    }
    await sketch.createSketchLine({
      startPoint:new Point(point1.x,point1.y),
      endPoint:new Point(point2.x,point2.y)});
  }
  async createCircleByTwoPoint(sketch,point1,point2){
    if(!sketch){
      return;
    }
    await sketch.createCircle({
      centerPoint:new Point(point1.x,point1.y),
      circlePoint:new Point(point2.x,point2.y)});
  }
  async createCircleSketch(centerPoint,datumId,sketchName,diameter1,diameter2 = -1){
    let inCirclePoint = new THREE.Vector3(centerPoint.x + diameter1 / 2,centerPoint.y);

    let sketch = this.command.sketch;
    await sketch.createSketch({sketchName:sketchName, datumId: datumId});

    await this.createCircleByTwoPoint(sketch, centerPoint,inCirclePoint);
    if(diameter2 !== -1){
      let outCirclePoint = new THREE.Vector3(centerPoint.x + diameter2 / 2,centerPoint.y);
      await this.createCircleByTwoPoint(sketch, centerPoint,outCirclePoint);
    }

    await sketch.exitSketch();
    let res = await this.command.executeIncrementCommand(this.command.commandScript);
    await this.command.clearCommand();

    let currentFeature = res?.data?.modelData?.currentFeature;
    if (currentFeature && currentFeature.length > 0) {
      let sketchFeature = {
        id: currentFeature[0]?.id,
        name: currentFeature[0]?.name,
      }
      return sketchFeature;
    }
  }
  //Test
  async createPointSketch(points,datumId,sketchName){
    let sketch = this.command.sketch;
    await sketch.createSketch({sketchName:sketchName, datumId: datumId});

    for (const point of points) {
      let param = {
        x:point.x,
        y:point.y
      }
      await sketch.createPoint(param);
    }

    await sketch.exitSketch();
    let res = await this.command.executeIncrementCommand(this.command.commandScript);
    await this.command.clearCommand();

    let currentFeature = res?.data?.modelData?.currentFeature;
    if (currentFeature && currentFeature.length > 0) {
      let sketchFeature = {
        id: currentFeature[0]?.id,
        name: currentFeature[0]?.name,
      }
      return sketchFeature;
    }
  }
  //创建空心圆柱
  async drawHollowColumn(centerPoint,height,featureName,inDiameter,outDiameter = -1){
    //创建一个包含内外两个圆的圆环
    let sketchFeature = await this.createCircleSketch(centerPoint,8,featureName + "草图",inDiameter,outDiameter);

    //对草图进行拉伸得到空心圆柱形状
    let basicCircleFeature = await this.extrude(sketchFeature,height,height,featureName);

    return basicCircleFeature;
  }
  //创建链板样式的草图
  async createChainBoardSketch(point1,point2,inDiameter,outRadius,chainBoardHeight,sketchName,datumId){
    //链板上的折点与圆心的连线与双圆心连线的夹角
    let alpha = this.asin(chainBoardHeight / (outRadius * 2));
    let breakPoint11 = this.rotatePointAroundPoint(point1,point2,alpha,outRadius);
    let breakPoint12 = this.rotatePointAroundPoint(point1,point2,-alpha,outRadius);
    let breakPoint21 = this.rotatePointAroundPoint(point2,point1,alpha,outRadius);
    let breakPoint22 = this.rotatePointAroundPoint(point2,point1,-alpha,outRadius);

    let sketch = this.command.sketch;
    await sketch.createSketch({sketchName:sketchName, datumId: datumId});

    await this.createArcByCenter(sketch,point1,breakPoint11,breakPoint12);
    await this.createSketchLine(sketch,breakPoint12,breakPoint21);
    await this.createArcByCenter(sketch,point2,breakPoint21,breakPoint22);
    await this.createSketchLine(sketch,breakPoint22,breakPoint11);

    let circleCenterPoint1 = new THREE.Vector3(point1.x + inDiameter / 2 ,point1.y,point1.z);
    let circleCenterPoint2 = new THREE.Vector3(point2.x + inDiameter / 2 ,point2.y,point2.z);
    await this.createCircleByTwoPoint(sketch,point1,circleCenterPoint1);
    await this.createCircleByTwoPoint(sketch,point2,circleCenterPoint2);

    await sketch.exitSketch();
    let res = await this.command.executeIncrementCommand(this.command.commandScript);
    await this.command.clearCommand();

    let currentFeature = res?.data?.modelData?.currentFeature;
    if (currentFeature && currentFeature.length > 0) {
      let sketchFeature = {
        id: currentFeature[0]?.id,
        name: currentFeature[0]?.name,
      }
      return sketchFeature;
    }
  }
  async drawChainBoard(point1,point2,inDiameter,outRadius,chainBoardHeight,chainBoardThickness,featureName){

    //创建链板的草图
    let chainBoardSketch = await this.createChainBoardSketch(point1,point2,inDiameter,outRadius,chainBoardHeight,featureName + "链板草图","8");
    //链轮圆台基础特征拉伸
    let basicCircleFeature = await this.extrude(chainBoardSketch,chainBoardThickness,0,featureName);
    return basicCircleFeature;
  }

  async moveFeature(feature,direction,distance,featureName,copy = true){
    let featureEntities = await this.getEntitiesByFeature(feature);
    if(featureEntities.length === 0){
      return;
    }
    direction.normalize();
    let dir = new Direction();
    dir.setPoint(new Point(),new Point(direction.x,direction.y,direction.z));

    let params = {
      entityIds:featureEntities.map(feature => feature.id),
      copy:copy ? 1 : 0,
      distance:Math.abs(distance),
      startPoint:new Point(),
      direction:dir,
      reverse:distance >= 0 ? 0 : 1
    }

    let res = await this.command.solid.createTransformByDistanceIncrement(params,featureName);
    let currentFeature = res?.data?.modelData?.currentFeature;
    if (currentFeature && currentFeature.length > 0) {
      let curFeature = {
        id: currentFeature[0]?.id,
        name: currentFeature[0]?.name,
      }
      return curFeature;
    }
  }
  async rotateFeature(feature,rotatePoint,rotateLine,angle,featureName,copy = true){
    let featureEntities = await this.getEntitiesByFeature(feature);
    if(featureEntities.length === 0){
      return;
    }
    let dir = new Direction();
    dir.setPoint(new Point(),new Point(rotateLine.x,rotateLine.y,rotateLine.z));

    let params = {
      entityIds:featureEntities.map(feature => feature.id),
      copy:copy ? 1 : 0,
      startPoint:new Point(rotatePoint.x,rotatePoint.y,rotatePoint.z),
      angle:angle,
      distance:Math.abs(angle),
      axis:dir,
      reverse:angle >= 0 ? 0 : 1
    }

    let res = await this.command.solid.createTransformByRotateIncrement(params,featureName);
    let currentFeature = res?.data?.modelData?.currentFeature;
    if (currentFeature && currentFeature.length > 0) {
      let curFeature = {
        id: currentFeature[0]?.id,
        name: currentFeature[0]?.name,
      }
      return curFeature;
    }
  }
  async getEntitiesByFeature(feature) {
    let res = await this.query.getEntitiesByFeatureIds([feature?.id]);
    let entities = res?.data?.entities;
    // if(!entities || entities.length === 0 || !entities[0].id){
    //   let time = 0;
    //   while(true){
    //     await this.sleep(100);
    //
    //     res = await this.query.getEntitiesByFeatureIds([feature?.id]);
    //     entities = res?.data?.entities;
    //
    //     if(entities && entities.length !== 0 && entities[0].id){
    //       break;
    //     }
    //     time++;
    //     if(time > 10000){
    //       debugger;
    //     }
    //   }
    //   if(!entities || entities.length === 0 || !entities[0].id){
    //     debugger;
    //   }
    // }
    return entities?.length > 0 ? entities : null;
  }
  async getEntitiesByFeatures(features){
    let res = await this.query.getEntitiesByFeatureIds(features.map(feature => feature.id));
    let entities = res?.data?.entities;
    return entities;
  }
  //拉伸
  async extrude(sketchFeature, dis1,dis2,featureName) {
    if (sketchFeature) {
      let entities = await this.getEntitiesByFeature(sketchFeature);
      if (entities && entities.length > 0) {
        let res = await this.command.solid.extrudeIncrement({
          sketch: entities[0]?.id,
          height1: dis1,
          extrudeType2:dis2 === 0 ? -1 : 0,
          height2: dis2,
        }, featureName);
        let currentFeature = res?.data?.modelData?.currentFeature;
        if (currentFeature && currentFeature.length > 0) {
          let feature = {
            id: currentFeature[0]?.id,
            name: currentFeature[0]?.name,
          }
          return feature;
        }
      }
    }
  }
  //旋转切除
  async revolveCut(sketchFeature,axisPoint,axisDir,cutFeature,featureName){
    let sketchEntities = await this.getEntitiesByFeature(sketchFeature);
    if(sketchEntities.length === 0){
      return;
    }
    let cutFeatureEntities = await this.getEntitiesByFeature(cutFeature);
    if(cutFeatureEntities.length === 0){
      return;
    }


    let axis = new Axis();
    axis.setPoint(new Point(axisPoint.x, axisPoint.y, axisPoint.z), new Point(axisPoint.x + axisDir.x, axisPoint.y + axisDir.y, axisPoint.z + axisDir.z));

    let params = {
      sketch:sketchEntities[0].id,
      axis:axis,
      cutSolids:[cutFeatureEntities[0].id],
      angle1:360,
    }
    let res = await this.command.solid.revolveCutIncrement(params,featureName);

    let currentFeature = res?.data?.modelData?.currentFeature;
    if (currentFeature && currentFeature.length > 0) {
      let feature = {
        id: currentFeature[0]?.id,
        name: currentFeature[0]?.name,
      }
      return feature;
    }
  }
  //圆周阵列
  async loftCircularPattern(loftFeature,axisPoint,axisDir, teethNumber,featureName) {
    if (!loftFeature) {
      return;
    }
    let axis = new Axis();
    axis.setPoint(new Point(axisPoint.x, axisPoint.y, axisPoint.z), new Point(axisPoint.x + axisDir.x, axisPoint.y + axisDir.y, axisPoint.z + axisDir.z));

    let entities = await this.getEntitiesByFeature(loftFeature);
    if (entities && entities.length > 0) {
      let res = await this.command.solid.circularPatternIncrement({
        baseType: 0, body: entities[0]?.id, axis: axis, angle1: 360, instanceNum1: teethNumber,
      }, featureName);

      let currentFeature = res?.data?.modelData?.currentFeature;
      if (currentFeature && currentFeature.length > 0) {
        let feature = {
          id: currentFeature[0]?.id,
          name: currentFeature[0]?.name,
        }
        return feature;
      }
    }
  }
  //布尔运算
  async booleanSub(extrudeFeature, loftFeature,featureName, circularPatternFeature = null) {
    if (!extrudeFeature || !loftFeature) {
      return;
    }
    let extrudeEntities = await this.getEntitiesByFeature(extrudeFeature);
    let loftEntities = await this.getEntitiesByFeature(loftFeature);
    let cutSolidIds = [], targetSolidId;
    if(circularPatternFeature){
      let circularPatternRes = await this.toolQuery.getEntitiesByFeatureId(circularPatternFeature?.id);
      let circularPatternEntities = circularPatternRes?.data?.entities;
      if(circularPatternEntities){
        circularPatternEntities.forEach(entity => {
          cutSolidIds.push(entity.id);
        });
      }
    }

    if (extrudeEntities && loftEntities) {
      cutSolidIds.push(loftEntities[0]?.id);

      targetSolidId = extrudeEntities[0]?.id;
      let res = await this.command.solid.booleanSubtractIncrement({
        entityBs: cutSolidIds,
        entityA: targetSolidId,
        keep: 0
      }, featureName);

      let currentFeature = res?.data?.modelData?.currentFeature;
      if (currentFeature && currentFeature.length > 0) {
        let feature = {
          id: currentFeature[0]?.id,
          name: currentFeature[0]?.name,
        }
        return feature;
      }
    }
  }

  async booleanUnion(listFeature,featureName = "合并"){
    if(listFeature.length < 2){
      return;
    }
    let entities = await this.getEntitiesByFeatures(listFeature);

    let res = await this.command.solid.booleanUnionIncrement({
      entitys: entities.map(entity => entity.id),
    }, featureName);

    let currentFeature = res?.data?.modelData?.currentFeature;
    if (currentFeature && currentFeature.length > 0) {
      let feature = {
        id: currentFeature[0]?.id,
        name: currentFeature[0]?.name,
      }
      return feature;
    }
  }
  //计算两点组成的线段变换成为另一个两点线段的参数
  async calculateTransformParam(point11,point12,point21,point22){
    //首先进行判断，如果点点之间的距离不相等，无法进行变换，此变换只关注旋转平移，不关系缩放比例
    let vect1 = point12.clone().sub(point11);
    let vect2 = point22.clone().sub(point21);
    let dis1 = (vect1).length();
    let dis2 = (vect2).length();

    //移动距离
    let moveDis = (point21.clone().sub(point11)).length();
    //移动方向
    let moveDir = (point21.clone().sub(point11)).normalize();

    let angle = 0;
    let rotateDir = new THREE.Vector3(0,0,1);
    //如果没有旋转，不需要进行旋转
    let dotValue = vect1.clone().normalize().dot(moveDir);
    if(dotValue < 0.999){
      //旋转角度
      angle = this.acos(vect1.clone().dot(vect2) / (dis1 * dis2));
      //存在旋转的情况可以解出旋转轴
      rotateDir = new THREE.Vector3().crossVectors(vect1,vect2);
      rotateDir.normalize();
    }
    let transParam = {
      moveDis:moveDis,
      moveDir:moveDir,
      rotatePoint:point21,
      rotateAngle:angle,
      rotateDir:rotateDir
    }
    return transParam;
  }


  //计算相切点
  calculateTangentPoint(center1,center2,radius1,radius2,normal) {
    let distance = (center1.clone().sub(center2)).length();
    //第一个圆心到切点向量与O1O2之间的角度
    let angle1 = this.acos((radius1 - radius2) / distance);
    //第二个圆心到切点向量与O1O2之间的角度
    let angle2 = 180 - angle1;

    //从法线正向看过去，左侧为圆1，右侧为圆2
    //通过角度及旋转轴，可以将另一个圆心进行旋转再乘半径得到切点
    //上侧两个相切点
    let tanPoint11 = this.getLineRevolvePoint(normal,center1,center2,angle1,radius1);
    let tanPoint21 = this.getLineRevolvePoint(normal,center2,center1,-angle2,radius2);

    //下侧两个相切点
    let tanPoint12 = this.getLineRevolvePoint(normal,center1,center2,-angle1,radius1);
    let tanPoint22 = this.getLineRevolvePoint(normal,center2,center1,angle2,radius2);

    let tanPoints = {
      tanPoint11:tanPoint11,                      //第一个圆的上切点
      tanPoint12:tanPoint12,                      //第一个圆的下切点
      tanPoint21:tanPoint21,                      //第二个圆的上切点
      tanPoint22:tanPoint22                       //第二个圆的下切点
    }
    return tanPoints;
  }
  //计算一组点中位于一个点某个方位最近的点
  async calculateNearPointOnSide(point,listPoint,side,center = new THREE.Vector3(0,0,0),normal = new THREE.Vector3(0,0,1),u = new THREE.Vector3(1,0,0),v = new THREE.Vector3(0,1,0)){
    let nearPointNo = -1;
    let dis = 100000000;
    for(let n = 0;n < listPoint.length;n++){
      let curPoint = listPoint[n];
      if(side === this.SIDE.POSITIVE || side === this.SIDE.NEGATIVE){
        //首先确定是否在对应的正反向
        let angle = this.getPointsAngle(center,point,curPoint,normal);
        if((angle > 0 && side === this.SIDE.NEGATIVE) || (angle < 0 && side === this.SIDE.POSITIVE)){
          continue;
        }
      }else if(side === this.SIDE.UP || side === this.SIDE.DOWN){
        let dir = curPoint.clone().sub(point);
        let dotValue = dir.clone().dot(v);
        if((dotValue < 0 && side === this.SIDE.UP) || (dotValue > 0 && side === this.SIDE.DOWN)){
          continue;
        }
      }else if(side === this.SIDE.LEFT || side === this.SIDE.RIGHT){
        let dir = curPoint.clone().sub(point);
        let dotValue = dir.clone().dot(u);
        if((dotValue < 0 && side === this.SIDE.RIGHT) || (dotValue > 0 && side === this.SIDE.LEFT)){
          continue;
        }
      }

      let tempDis = (point.clone().sub(curPoint)).length();
      if(tempDis < dis){
        nearPointNo = n;
        dis = tempDis;
      }
    }
    return nearPointNo;
  }

  //二维上给定两个点，以及中间线段的数量*线段的长度，计算每个点的位置，以及给定两个点的切向，！！！！！！！！！！！需要考虑重力因素
  calculatePointPosByGravity(point1,point2,num,length){
    //如果距离比中间线段长度大，返回错误
    let dis = (point1.clone().sub(point2)).length();
    if(num * length < dis){
      return;
    }

    //暂时使用圆弧代替悬链线计算
    //求解公式很复杂，使用迭代法进行计算
    //直线12垂直平分线的向量
    let dirToCenter = (new THREE.Vector3(-(point2.y - point1.y) / (point2.x - point1.x),1)).clone().normalize();

    let step = 10000000;
    let center = this.calculateCenterPoint(point1,point2,dirToCenter.clone().multiplyScalar(step),num,length,step,this.SIDE.IN);

    if(center === null){
      return;
    }

    //计算圆中心到12两点的夹角
    let angle = this.getPointsAngle(center,point1,point2);
    //计算所有点的坐标
    let points = [];
    for(let n = 1;n < num;n++){
      //小链节对应的角度
      let pAngle = angle * n / num;
      //从圆中心依次进行旋转计算每个点坐标
      let point = this.rotatePointAroundPoint(center,point1,pAngle);
      points.push(point);
    }

    //计算左右两侧点的斜率
    let pointSlope1 = this.calculateSlopeOnCircle(center,point1);
    let pointSlope2 = this.calculateSlopeOnCircle(center,point2);

    let pointsInfo = {
      slope1:pointSlope1,
      slope2:pointSlope2,
      points:points
    }

    return pointsInfo;
  }
  //已知圆心在x = ky + b直线上，迭代计算圆心
  //两点间的点数量，vectorToCenter两点中心到圆心的方向、距离,，length相邻点间的距离，step为当前变化的步长，下次取半
  //side为下次取值向内还是向外
  calculateCenterPoint(point1,point2,vectorToCenter,num,length,step,side = this.SIDE.OUT){
    //如果求解到极小范围还未求出解返回null
    if(step < 0.001){
      return;
    }
    let centerPoint12 = (point1.clone().add(point2)).multiplyScalar(0.5);
    //圆心为x,y,求解两点的圆心角
    let centerPoint = centerPoint12.clone().add(vectorToCenter);
    let angle = this.getPointsAngle(centerPoint,point1,point2);

    //圆半径
    let radius = (centerPoint.clone().sub(point1)).length();
    //根据圆心角求解小段圆心角对应的弦长
    let chordLength = this.sin(0.5 * angle / num) * radius * 2;

    if(Math.abs(chordLength - length) < 0.001){
      return centerPoint;
    }else{
      //某一点处是否求出的弦长过大或过小，前进方向进行变更
      if(chordLength - length < 0){
        side = this.SIDE.IN;
      }else{
        side = this.SIDE.OUT;
      }
      let vectorLength = vectorToCenter.clone().length();

      //向内为负向外为正，每次步长为上次的一半
      let k = side === this.SIDE.OUT ? 1 : -1;
      vectorToCenter = vectorToCenter.clone().normalize().multiplyScalar(vectorLength + k * step / 2);
      return this.calculateCenterPoint(point1,point2,vectorToCenter,num,length,step / 2,side);
    }
  }
  //计算圆上某点处的斜率
  calculateSlopeOnCircle(center,point){
    let dirToCenter = point.clone().sub(center);
    //斜率不存在
    if(dirToCenter.y === 0){
      return null;
    }
    let pointSlope = -dirToCenter.x / dirToCenter.y;
    return pointSlope;
  }
  //计算两点斜率
  calculateSlopeOnTwoPoint(point1,point2){
    let dir = point2.clone().sub(point1);
    if(dir.x === 0){
      return null;
    }
    let slope = dir.y / dir.x;
    return slope;
  }

  //计算线线相交点
  calculateIntersectPoint(point11,point12,point21,point22){
    let dir1 = point12.clone().sub(point11);
    let dir2 = point22.clone().sub(point21);
    dir1.normalize();
    dir2.normalize();
    //如果两线平行，不能进行相交返回
    if(Math.abs(dir1.x * dir2.y - dir1.y * dir2.x) < 0.001){
      return;
    }

    let dir1121 = point21.clone().sub(point11);
    //计算point21到直线1的距离
    let dis21To1 = (new THREE.Vector3().crossVectors(dir1121,dir1)).length();
    //point21投影点的坐标
    let prjPoint21ToDir1 = point11.clone().add(dir1.clone().multiplyScalar(dir1121.clone().dot(dir1)));
    //两直线夹角
    let cosTheta = Math.abs(dir1.clone().dot(dir2));

    let interPoint;
    if(cosTheta === 0){
      //两直线垂直
      interPoint = prjPoint21ToDir1;
    }else{
      let tanTheta = (1 - cosTheta ** 2) ** 0.5 / cosTheta;
      //交点到垂点距离
      let disInterPntToProPnt = dis21To1 / tanTheta;

      //验证交点是在垂点的延长线上，还是在垂点内
      let testInterPnt = prjPoint21ToDir1.clone().add(dir1.clone().multiplyScalar(disInterPntToProPnt));

      //判断当前验证交点是否在直线2上
      let testDir2 = testInterPnt.clone().sub(point21);
      //如果与dir2平行，是交点，不平行则不是
      if(Math.abs(testDir2.x * dir2.y - testDir2.y * dir2.x) < 0.001){
        interPoint = testInterPnt;
      }else{
        testInterPnt = prjPoint21ToDir1.clone().sub(dir1.clone().multiplyScalar(disInterPntToProPnt));
      }
    }

    if(interPoint === null){
      debugger;
    }

    if(Math.abs(interPoint.x) < 0.001){
      interPoint.x = 0;
    }
    if(Math.abs(interPoint.y) < 0.001){
      interPoint.y = 0;
    }
    if(Math.abs(interPoint.z) < 0.001){
      interPoint.z = 0;
    }

    return interPoint;
  }
  //计算线线相交
  calculateLineInterLine(point11,point12,point21,point22){
    let dir1 = point12.clone().sub(point11);
    let dir2 = point22.clone().sub(point21);
    dir1.normalize();
    dir2.normalize();
    //如果两线平行，不能进行相交返回
    if(Math.abs(dir1.x * dir2.y - dir1.y * dir2.x) < 0.001){
      return;
    }

    //k1 * dir1 + P12 = k2 * dir2 + P22
    //k1*x1 - k2*x2 = (P22 - P12).x;
    //k1*y1 - k2*y2 = (P22 - P12).y;

    let k1 = ((point22.y - point12.y) * dir2.x - (point22.x - point12.x) * dir2.y) / (dir2.x * dir1.y - dir1.x * dir2.y);
    let interPoint = point12.clone().add(dir1.clone().multiplyScalar(k1));
    return interPoint;
  }

//两点垂直平分线上求解到一个点固定距离的点
  calculateCenterPtByDis(point1,point2,pointDis,dis){
    //垂直平分线上点
    let centerPt = (point1.clone().add(point2)).multiplyScalar(0.5);
    //两点方向
    let dir12 = (point2.clone().sub(point1)).normalize();
    //垂直平分线方向
    let dirCenter = new THREE.Vector3(-dir12.y,dir12.x);

    //求解垂直平分线方程
    if(dirCenter.x !== 0){
      //如果存在斜率的情况
      let k = dirCenter.y / dirCenter.x;
      let b0 = centerPt.y - k * centerPt.x;

      //通过直线方程与圆弧距离方程联立
      let a = 1 + k * k;
      let b = -2 * pointDis.x + 2 * k * (b0 - pointDis.y);
      //let b = -2 * (b0 * k + k * pointDis.y + pointDis.x)
      let c = Math.pow(pointDis.x,2) + Math.pow(b0 - pointDis.y,2) - dis * dis;
      //let c = Math.pow(b0,2) + Math.pow(pointDis.x,2) + Math.pow(pointDis.y,2)  + 2 * b0 * pointDis.y - dis * dis;

      //求解x，y
      let x = (-b + Math.pow(b * b - 4 * a * c,0.5)) / (2 * a);
      let y = k * x + b0;
      let newPoint = new THREE.Vector3(x,y);
      return newPoint;
    }else{
      //如果垂直平分线为平行于y轴，则不存在斜率,垂直平分线的方程为x = centerPt.x;
      let a = Math.pow(dis,2);
      let b = Math.pow((centerPt.x - pointDis.x),2);
      let c = a - b;
      let d = Math.pow(c,0.5);


      let y = pointDis.y + Math.pow((Math.pow(dis,2) - Math.pow((centerPt.x - pointDis.x),2)),0.5);
      let newPoint = new THREE.Vector3(centerPt.x,y);
      return newPoint;
    }
  }

  //保留小数位数
  restoreDecimal(num,decimalNum){
    let newNum = Math.round((num * Math.pow(10,decimalNum))) / Math.pow(10,decimalNum);
    return newNum;
  }
  //线面求交点
  getIntersectPoint(linePoint,lineDir,planePoint,planeNormal){
    //判断直线不与平面平行
    if(lineDir.clone().dot(planeNormal) === 0){
      return;
    }
    lineDir.normalize();

    //直线上点在平面的投影
    let linePointProject = this.pointProject(planeNormal,planePoint,linePoint);
    //直线点到直线点投影的向量
    let vectLinePointToProject = linePointProject.clone().sub(linePoint);
    //直线点到直线点投影的距离
    let length = vectLinePointToProject.clone().length();

    vectLinePointToProject.normalize();

    //直线方向与法向的夹角
    let alpha = Math.acos(vectLinePointToProject.clone().dot(lineDir));
    //交点在直线点上的偏移
    let vectOffsetDis = length / Math.cos(alpha);

    //交点
    let intersectPoint = linePoint.clone().add(lineDir.clone().multiplyScalar(vectOffsetDis));
    return intersectPoint;
  }
  //点在面上的投影点
  pointProject(dir,origin,point){
    let pointToOrigin = origin.clone().sub(point);
    let dirNor = dir.clone().normalize();
    let oriNor = pointToOrigin.clone().normalize();
    let alpha = Math.acos(dirNor.clone().dot(oriNor));
    let projectDis = pointToOrigin.length() * Math.cos(alpha);
    let projectPoint = point.clone().add(dirNor.clone().multiplyScalar(projectDis));
    return projectPoint;
  }

  tan(num){
    return Math.tan(num * Math.PI / 180);
  }
  cos(num){
    return Math.cos(num * Math.PI / 180);
  }
  sin(num){
    return Math.sin(num * Math.PI / 180);
  }
  acos(num){
    return Math.acos(num) * 180 / Math.PI;
  }
  asin(num){
    return Math.asin(num) * 180 / Math.PI;
  }
  async sleep(delay) {
    return new Promise(resolve => setTimeout(resolve, delay));
  }

}

const chainDriveDesignCommand = new ChainDriveDesignCommand();
export {chainDriveDesignCommand};
